#pragma once
#include <vector>

namespace krryn{
namespace core{
	//! There is only a base class so we can 
	//! access static members and the typedef
	//! of this class.
	class tag_base{
	public:
		typedef size_t value_type;

		tag_base() : m_Id(m_NumberOfTags++) {}
		value_type get_id() const {return m_Id;}
		static value_type get_tag_count() {return m_NumberOfTags;}
	private:
		tag_base &operator=(const tag_base&);

		const value_type m_Id;
		static value_type m_NumberOfTags;
	};

	template<typename _Type>
	class tag : public tag_base{
	public:
		typedef _Type interface_type;
	};

	//! This container contains a maximum of 
	//! 2 ^ sizeof(tag_base::value_type) elements
	class tag_container{
	public:
		tag_container() : m_Instances(tag_base::get_tag_count()) {}

		template<typename _Tag>
		typename _Tag::interface_type *get(_Tag a_Tag) const{
			return static_cast<typename _Tag::interface_type*>(m_Instances[a_Tag.get_id()]);
		}

		template<typename _Tag>
		void set(_Tag a_Tag, typename _Tag::interface_type *a_Object){
			m_Instances[a_Tag.get_id()] = a_Object;
		}
	private:
		std::vector<void*> m_Instances;
	};
}
}
